package com.sunshine.serialport.tools;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.StringUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @classDescription:bean 将bean转换成map
 * @author:xiayingjie
 * @createTime:15/5/26
 */

public class BeanInfoUtil {
    static Gson gson = new GsonBuilder()
            .excludeFieldsWithoutExposeAnnotation()
            .enableComplexMapKeySerialization()
            .serializeNulls()
            .setDateFormat("yyyy-MM-dd")
            .setPrettyPrinting()
            .setVersion(1.0)
            .create();




    /**
     * 将bean 转换成map对象
     *
     * @param bean
     * @param exclude    "id,roles" 移除id和roles属性
     * @param includeMap 添加新的map
     * @param replace    替换属性 “id:userId” 比如将id替换成userId
     * @return
     */
    public static Map<String, Object> bean2map(Object bean, String exclude, Map<String, Object> includeMap, String replace) {
        Map<String, Object> map = new HashMap();
        try {
            Set<String> excludeSet = null;
            boolean exExist = true;
            boolean inExist = true;
            Map<String, String> replaceMap = null;
            if (StringUtils.isNotBlank(exclude)) {
                String[] es = StringUtils.split(exclude, ",");
                excludeSet = Sets.newHashSet(es);
            } else {
                exExist = false;
            }
            if (StringUtils.isNotBlank(replace)) {
                String[] rss = StringUtils.split(replace, ",");
                replaceMap = Maps.newLinkedHashMap();
                for (String s : rss) {
                    String[] rs = StringUtils.split(s, ":");
                    replaceMap.put(rs[0], rs[1]);
                }
            } else {
                inExist = false;
            }
            BeanInfo b = Introspector.getBeanInfo(bean.getClass());
            PropertyDescriptor[] propertyDescriptors = b.getPropertyDescriptors();

            for (PropertyDescriptor p : propertyDescriptors) {
                String key = p.getName();
                if ("class".equals(key)) {
                    continue;
                }

                if (exExist && excludeSet.contains(key)) {
                    continue;
                }
                if (inExist && excludeSet.contains(key)) {
                    key = replaceMap.get(key);
                }

                Method readMethod = p.getReadMethod();
                Object result = readMethod.invoke(bean);


                List list = null;
                //用来解决数组进行传递参数的问题
                if (result == null) {
                    map.put(key, "");
                    continue;
                }
                if(result instanceof String) {
                    if (((String) result).startsWith("[") && ((String) result).endsWith("]")) {
                        String res = EncodeUtil.htmlUnescape((String) result);
                        list = gson.fromJson(res, new TypeToken<ArrayList>() {
                        }.getType());
                        map.put(key, list);
                        continue;
                    }

                }
                //转换首字母大写
                //key = StringUtils.capitalize(key);
                map.put(key, result);

            }


        } catch (Exception e) {
            e.printStackTrace();

        }
        if (null != includeMap) {
            map.putAll(includeMap);
        }

        return map;

    }

    /**
     * 将bean 转换成map对象
     *
     * @param bean
     * @param exclude    "id,roles" 移除id和roles属性
     * @param includeMap 添加新的map
     * @return
     */
    public static Map<String, Object> bean2map(Object bean, String exclude, Map<String, Object> includeMap) {
        return bean2map(bean, exclude, includeMap, null);
    }
    /**
     * 将bean 转换成map对象
     *
     * @param bean
     * @param replace    替换属性 “id:userId” 比如将id替换成userId
     * @return
     */
    public static Map<String, Object> bean2mapReplace(Object bean,  String replace ) {
        return bean2map(bean, null, null, replace);
    }
    /**
     * 将bean 转换成map对象
     *
     * @param bean
     * @param exclude    "id,roles" 移除id和roles属性
     * @return
     */
    public static Map<String, Object> bean2mapExclude(Object bean,  String exclude ) {
        return bean2map(bean, exclude, null, null);
    }



    /**
     * 将bean 转换成map对象
     *
     * @param bean
     * @param includeMap 添加新的map
     * @return
     */
    public static Map<String, Object> bean2map(Object bean, Map<String, Object> includeMap) {
        return bean2map(bean, null, includeMap);
    }

    /**
     * 将bean 转换成map对象
     *
     * @return
     */
    public static Map<String, Object> bean2map(Object bean) {
        return bean2map(bean, null, null,null);
    }

    /**
     * 将list转换成map对象
     *
     * @param beanlist 被转换的list对象
     * @param exclude  list里面的属性移除
     * @return
     */
    public static List<Map<String, Object>> list2mapExclude(List<Object> beanlist, String exclude) {
        List<Map<String, Object>> list = Lists.newArrayList();
        for (Object bean : beanlist) {
            list.add(bean2mapExclude(bean, exclude));
        }
        return list;
    }

    /**
     * 将list转换成map对象
     *
     * @param beanlist 被转换的list对象
     * @return
     */
    public static List<Map<String, Object>> list2map(List beanlist) {
        List<Map<String, Object>> list = Lists.newArrayList();
        if (beanlist != null) {
            for (Object bean : beanlist) {
                list.add(bean2map(bean));
            }
        }
        return list;
    }


    /**
     * 只支持基本类型
     *
     * @param src
     * @param desc
     * @return
     */
    public static Object bean2bean(Object src, Object desc) {
        return bean2bean(src, desc, null);
    }

    /**
     * 只支持基本类型
     *
     * @param src     来源对象
     * @param desc    输出对象
     * @param exclude "user,name"  不包含某些属性
     * @return
     */
    public static Object bean2bean(Object src, Object desc, String exclude) {
        try {
            BeanInfo srcBean = Introspector.getBeanInfo(src.getClass());
            BeanInfo descBean = Introspector.getBeanInfo(desc.getClass());
            PropertyDescriptor[] descPDs = descBean.getPropertyDescriptors();
            PropertyDescriptor[] srcPDs = srcBean.getPropertyDescriptors();

            //不覆盖的属性
            Set<String> excludeSet = null;
            if (!StringUtils.isBlank(exclude)) {
                String[] es = StringUtils.split(exclude, ",");
                excludeSet = Sets.newHashSet(es);

            }
            //循环遍历属性
            for (PropertyDescriptor dp : descPDs) {
                String name = dp.getName();
                boolean isCheck = !"class".equals(name) && (excludeSet == null || !excludeSet.contains(name));
                if (isCheck) {

                    for (PropertyDescriptor sp : srcPDs) {

                        if (name.equals(sp.getName())) {
                            Method readMethod = sp.getReadMethod();
                            Object result = readMethod.invoke(src);

                            if (checkNull(result)) {
                                Method writeMethod = dp.getWriteMethod();
                                writeMethod.invoke(desc, result);
                            }
                            break;
                        }

                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return desc;
    }

    /**
     * 检查对象是否为空
     *
     * @param result
     * @return
     */
    public static boolean checkNull(Object result) {
        boolean flag = false;
        if (result instanceof String) {
            flag = !StringUtils.isBlank((String) result);
        } else if (result instanceof Integer) {
            flag = (int) result != 0 ? true : false;
        } else if (result instanceof Long) {
            flag = (long) result != 0L ? true : false;
        } else if (result instanceof Float) {
            flag = (float) result != 0L ? true : false;
        } else if (result instanceof Double) {
            flag = (double) result != 0D ? true : false;
        } else if (null != result) {
            flag = true;
        }
        return flag;

    }

    public static void main(String[] args) {

    }
}